/*
 * Projekt do předmetu GJA - LATEX TABLE CREATOR
 *
 * Soubor: MSCTSelectionListener.java
 *
 * Ondřej Klubal <xkluba00@stud.fit.vutbr.cz>
 * Petr Šimon    <xsimon10@stud.fit.vutbr.cz>
 */

package table;

import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.*;

/**
 * Pozorovatel zpráv výběru tabulky <code>MultiSpanCellTable</code>.
 * Řeší výběr sloučených buňek.
 */
public class MSCTSelectionListener implements ListSelectionListener
{
     MultiSpanCellTable table; //!< Hlavní tabulka
     JTable rowHeader;  //!< RowHeader tabulka
     boolean safe; //!< rekuzrivní zarážka
     int lastRow1;
     int lastCol1;
     int lastRowG;
     int lastColG;
     int lastRowOffset;
     int lastColOffset;
     boolean changed;
     
     /**
      * Konstruktor, inicializace.
      * @param table hlavní tabulka
      * @param rowHeader postraní header
      */
     public MSCTSelectionListener(MultiSpanCellTable table, JTable rowHeader)
     {
          this.table = table;
          this.rowHeader = rowHeader;
          safe = true;
          lastRow1 = 0;
          lastCol1 = 0;
          lastRowG = 0;
          lastColG = 0;
          lastRowOffset = 0;
          lastColOffset = 0;
          changed = false;
     }
     
     /**
      * Došlo k vyvolání události změny výběru.
      * Protože by mohlo docházet k rekurzivní změně výběru ->safe pojistka.
      * Je zajištěno zejména bezpečné procházení tabulky za cenu některých nekorektností při výběru.
      * Nedochází ke vstupu na neviditelné buňky.
      * Zvýrazňuje také vybrané řádky v rowheaderu.
      * @param e událost změny
      */
     public void valueChanged(ListSelectionEvent e)
     {
     
          //System.out.print("x|"+ table.getSelectedColumns().length + "|" +table.getSelectedRows().length+" ");
          if (!safe) return; //rekurzivní zarážka
          
          
          if (e.getSource() == table.getSelectionModel() || e.getSource() == table.getColumnModel().getSelectionModel()) //table.getRowSelectionAllowed() && table.getColumnSelectionAllowed()
          {
               //if (e.getSource() == table.getSelectionModel()) System.out.println("SR"); else System.out.println("SC");
               
               //změna sloupce
               int[] columns = table.getSelectedColumns();
               int[] rows    = table.getSelectedRows();
               
               int rowMax    = rows.length;
               int columnMax = columns.length;
               
               if ((rowMax > 0) && (columnMax > 0))
               {
               
                    //přístup k modelu
                    TableModel model = table.getModel();
                    
                    //model může obsahovat paramety - nařteme je
                    
                    if (model instanceof AttributiveCellTableModel)
                    {
                         CellAttribute cellAtt = ((AttributiveCellTableModel)model).getCellAttribute();
                         
                         if (cellAtt instanceof CellSpan)
                              if ((rowMax == 1) && (columnMax == 1))
                              {
                                   int row = table.getSelectedRow();
                                   int col = table.getSelectedColumn();
                                   
                                   //zjistíme posun
                                   int row_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.ROW];
                                   int col_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.COLUMN];
                                   
                                   //System.out.println("O: "+row_offset+" "+col_offset+ " R:"+ table.getSelectedRow() +" "+ table.getSelectedColumn());
                                   
                                   
                                   // if ((row_offset<0) && (col_offset<=0) && ((lastRowOffset==row_offset) || (lastColOffset==col_offset))) changed=true;
                                   
                                   lastRowOffset = row_offset;
                                   lastColOffset = col_offset;
                                   
                                   if ((lastColG > 0))//&& ((row_offset==-1) || (col_offset==-1)))
                                   {
                                        if (changed)
                                        {
                                             changed = false;
                                        }
                                        else
                                        {
                                             if (row_offset < 0)
                                             {
                                                  //   col=lastCol1; row=lastRow1;//lastRowG-1;
                                             }
                                             
                                             if (col_offset < 0)
                                             {
                                                  //    row=lastRow1; col=lastCol1;//G-1;
                                             }
                                             
                                             lastColG = 0;
                                             lastRowG = 0;
                                             row_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.ROW];
                                             col_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.COLUMN];
                                        }
                                   }
                                   
                                   //klasická buňka
                                   if (row_offset == 1) { lastRow1 = row; lastRowG = 0;}
                                   
                                   if (col_offset == 1) { lastCol1 = col; lastColG = 0;}
                                   
                                   //podíváme se na sloučené buňky
                                   
                                   if (row_offset <= 0) { row += row_offset; }
                                   
                                   if (col_offset <= 0) { col += col_offset; }
                                   
                                   
                                   //  System.out.println("O: "+row_offset+" "+col_offset+ " R:"+ table.getSelectedRow() +" "+ table.getSelectedColumn());
                                   safe = false; //kritická (rekurzivní sekce)  !!zabránění rekurzi
                                   table.changeSelection(row, col, false, false); //přidáme k výběru
                                   safe = true; //opětovné povolení rekuze
                                   
                                   //načteme nový posun (parametry sloučené buňky
                                   row_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.ROW];
                                   col_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.COLUMN];
                                   
                                   //jedná se o sloučenou buňku
                                   if ((row_offset > 1) || (col_offset > 1))  { lastRowG = row_offset; lastColG = col_offset; }
                                   
                                   
                                   ///  System.out.println("A: "+row+" "+col+ " B:"+ table.getSelectionModel().getLeadSelectionIndex() +" "+ table.getColumnModel().getSelectionModel().getLeadSelectionIndex());
                                   //  System.out.println("1: "+lastRow1+" "+lastCol1+ " G:"+ lastRowG +" "+ lastColG);
                                   
                                   
                              }
                              else
                                   for (int i = rowMax - 1; i >= 0; i--)
                                   {
                                        int row = rows[i];
                                        
                                        for (int j = columnMax - 1; j >= 0; j--)
                                        {
                                             int col = columns[j];
                                             
                                             safe = false; //kritická (rekurzivní sekce)  !!zabránění rekurzi
                                             table.changeSelection(row, col, true, true);
                                             safe = true; //opětovné povolení rekuze
                                             
                                             for (int b = 0; b < 2; b++)   //na pokrytí sloučené buňky jsou třeba 2 cykly
                                             {
                                                  int row_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.ROW];
                                                  int col_offset = ((CellSpan) cellAtt).getSpan(row, col)[CellSpan.COLUMN];
                                                  
                                                  //podíváme se na sloučené buňky
                                                  if (row_offset > 0) row += row_offset - 1; else row += row_offset;
                                                  if (col_offset > 0) col += col_offset - 1; else col += col_offset;
                                                  
                                                  safe = false; //kritická (rekurzivní sekce)  !!zabránění rekurzi
                                                  table.changeSelection(row, col, true, true); //přidáme k výběru
                                                  safe = true; //opětovné povolení rekuze
                                             }
                                        }
                                   }
                    }
                    
                    
                    if (e.getValueIsAdjusting())
                    {
                         table.revalidate();
                         table.repaint();
                    }
                    
               }
               
               if (rowHeader != null) //promítneme výběr do rowheaderu
               {
                    int[] nrows = table.getSelectedRows();
                    
                    if (nrows.length < 1) return;
                    
                    int minRow = nrows[0];
                    int maxRow = nrows[0];
                    
                    for (int j = 0; j < nrows.length; j++)
                         if (nrows[j] < minRow) minRow = nrows[j];
                         else if (nrows[j] > maxRow) maxRow = nrows[j];
                         
                    if (maxRow >= rowHeader.getRowCount()) maxRow = rowHeader.getRowCount() - 1; //pojistka zajišťijící nepřekročení maximálního počtu řádků
                    
                    rowHeader.setRowSelectionInterval(minRow, maxRow);
                    rowHeader.repaint(); //je třeba překreslit vždy !!
               }
               
               table.getTableHeader().repaint(); //promítneme změny zvíraznění sloupců
          }
     }
}
